package com.wyzz.hr.util.reflect;

import java.io.PrintStream;
import java.lang.reflect.Method;

public class SetObjectProperty {

	public SetObjectProperty() {
		arrayLength = 0;
	}

	public SetObjectProperty(Class objClass, String fieldName) throws Exception {
		arrayLength = 0;
		initial(objClass, fieldName);
	}

	public void initial(String className, String fieldName) throws Exception {
		initial(Class.forName(className), fieldName);
	}

	public void initial(Class objClass, String fieldName) throws Exception {
		if (fieldName == null || fieldName.length() < 1) {
			System.out.println((new StringBuilder()).append(
					"==========error: fieldName is null: (").append(
					objClass.getName()).append(" , ").append(fieldName).append(
					")").toString());
			throw new Exception();
		}
		this.fieldName = fieldName;
		String fieldNameArray[] = fieldName.split("\\.");
		arrayLength = fieldNameArray.length;
		smethods = new Method[arrayLength];
		gmethods = new Method[arrayLength];
		paraClass = new Class[arrayLength];
		Class objectClass = objClass;
		for (int i = 0; i < arrayLength; i++) {
			if (objectClass.getName().indexOf("com.wyzz.hr") != 0) {
				System.out
						.println((new StringBuilder())
								.append(
										"==========error: the declared class of fieldName should begin with com.hr: (")
								.append(objClass.getName()).append(" , ")
								.append(fieldName).append(")").toString());
				throw new Exception();
			}
			String methodNameTmp = (new StringBuilder()).append(
					fieldNameArray[i].substring(0, 1).toUpperCase()).append(
					fieldNameArray[i].substring(1)).toString();
			gmethods[i] = objectClass.getMethod((new StringBuilder()).append(
					"get").append(methodNameTmp).toString(), new Class[0]);
			paraClass[i] = gmethods[i].getReturnType();
			smethods[i] = objectClass.getMethod((new StringBuilder()).append(
					"set").append(methodNameTmp).toString(),
					new Class[] { paraClass[i] });
			objectClass = paraClass[i];
		}

	}

	public void setProperty(Object obj, Object property) throws Exception {
		if (property == null)
			return;
		Object property1;
		if (property.getClass().getName() == "java.lang.String"
				&& paraClass[arrayLength - 1].getName() == "java.lang.Integer") {
			property1 = Integer.valueOf(Integer.parseInt((String) property));
		} else {
			if (property.getClass().getName().compareTo(
					paraClass[arrayLength - 1].getName()) != 0) {
				System.out
						.println((new StringBuilder())
								.append(
										"==========error: parameter class is not correct: need ")
								.append(paraClass[arrayLength - 1].getName())
								.append(" , input ").append(
										property.getClass().getName())
								.toString());
				throw new Exception();
			}
			property1 = property;
		}
		Object objTmp = obj;
		for (int i = 0; i < arrayLength - 1; i++) {
			Object objTmp1 = gmethods[i].invoke(objTmp, new Object[0]);
			if (objTmp1 == null) {
				smethods[i].invoke(objTmp, new Object[] { paraClass[i]
						.newInstance() });
				objTmp = gmethods[i].invoke(objTmp, new Object[0]);
			} else {
				objTmp = objTmp1;
			}
		}

		smethods[arrayLength - 1].invoke(objTmp, new Object[] { property1 });
	}

	public static void setObjectProperty(Object obj, String fieldName,
			Object property) throws Exception {
		if (obj == null)
			return;
		if (fieldName == null || fieldName.length() < 1) {
			obj = property;
			return;
		}
		String fieldNameArray[] = fieldName.split("\\.");
		int arrayLength = fieldNameArray.length;
		Class objectClass = obj.getClass();
		Object objTmp = obj;
		for (int i = 0; i < arrayLength - 1; i++) {
			String methodNameTmp = (new StringBuilder()).append(
					fieldNameArray[i].substring(0, 1).toUpperCase()).append(
					fieldNameArray[i].substring(1)).toString();
			Method getMethod = objectClass.getMethod((new StringBuilder())
					.append("get").append(methodNameTmp).toString(),
					new Class[0]);
			Object objTmp1 = getMethod.invoke(objTmp, new Object[0]);
			if (objTmp1 == null) {
				Class paraClass = getMethod.getReturnType();
				Method setMethod = objectClass.getMethod((new StringBuilder())
						.append("set").append(methodNameTmp).toString(),
						new Class[] { paraClass });
				Object objTmp2 = paraClass.newInstance();
				setMethod.invoke(objTmp, new Object[] { objTmp2 });
				objTmp = objTmp2;
			} else {
				objTmp = objTmp1;
			}
		}

		String methodNameTmp = (new StringBuilder()).append(
				fieldNameArray[arrayLength - 1].substring(0, 1).toUpperCase())
				.append(fieldNameArray[arrayLength - 1].substring(1))
				.toString();
		Method getMethod = objectClass.getMethod((new StringBuilder()).append(
				"get").append(methodNameTmp).toString(), new Class[0]);
		Method setMethod = objectClass.getMethod((new StringBuilder()).append(
				"set").append(methodNameTmp).toString(),
				new Class[] { getMethod.getReturnType() });
		setMethod.invoke(objTmp, new Object[] { property });
	}

	public String getFieldName() {
		return fieldName;
	}

	public static final String fieldSeperator = "\\.";
	public static final String classPrefix = "com.hr";
	private String fieldName;
	private Method smethods[];
	private Method gmethods[];
	private Class paraClass[];
	private int arrayLength;
}
